local skynet = require "skynet"
local filelog = require "filelog"
local cluster = require "skynet.cluster"
local slottool = require "slottool"
local base = require "base"
local timetool = require "timetool"
local tabletool = require "tabletool"

require "pubenum"
require "ernnenum"

local robotmgr = {
    CMD = {},
    handler = {},
    robotpool = {},         --机器人池，从robot节点获取500个，缓存在本节点
    robotinfo_list = {},    --运行中机器人的robotinfo数组
    create_robotpool = {},
    is_runrobot = true,
    min_robot_num = 2,
}

--当前机器人数
local cur_robot_num = 0

--机器人列表
local robot_list = {}

--创建机器人
function robotmgr.cretae_robot(obj, base_diamond)
    obj = obj or {}
    local robotinfo = robotmgr.handler.get_robotinfo()
    if not robotinfo then
        return
    end
    local logo = robotinfo.logo or "1"
    local sex = robotinfo.sex or base.get_random(1,2)
    local rid = robotinfo.rid or base.get_random(111111,999999)
    local rolename = robotinfo.rolename or "_g" .. rid
    obj.roledata = {
        info = { 
            rolename = rolename,    --名字
            level = 99,             --等级
            logo = logo,            --头像
            sex = sex,              --性别
            rid = rid,
            },
        money = {
            diamond = 0,
            coin = 0,
            lock_coin = 0,
            lock_diamond = 0,
        },
        is_robot = true,
        table_address = -1,
        already_game_num = 0,
    }
    obj.rid = rid
    --随机diamond
    local min = base_diamond * 50
    local max = base_diamond * 80
    obj.roledata.money.diamond = base_diamond
    --保存机器人
    robot_list[rid] = 0
    if robotmgr.create_robotpool[rid] == nil then
        robotmgr.create_robotpool[rid] = tabletool.deepcopy(obj)
    end
    --保存robotinfo，方便回收
    robotmgr.robotinfo_list[rid] = robotinfo
    return obj
end

--添加机器人到桌子
function robotmgr.add_robot_to_table(table_service, table_index, robot_num, base_diamond)
    robot_num = robot_num or 1
    for i = 1,robot_num do
        local robot = robotmgr.cretae_robot({}, base_diamond)
        if robot then
            --进桌
            local status,result = skynet.pcall(skynet.call, table_service, "lua", "entertable", robot.rid, robot.roledata, {}, true)
            if status and result.retcode == nil then
                --坐下
                local msgbody = {
                    seat_index = 0,
                }
                status,result = skynet.pcall(skynet.call, table_service, "lua", "sitdowntable", robot.rid, robot.roledata, msgbody, true)
                if status and result.retcode == nil then
                    --准备
                    local r_msgbody = { table_index = 0 }
                    status,result = skynet.pcall(skynet.call, table_service, "lua", "gameready", robot.rid, robot.roledata, r_msgbody)
                end
                robot_list[robot.rid] = table_service
                cur_robot_num = cur_robot_num + 1
            else
                robotmgr.remove_robot(robot.rid)
            end
        end
    end
end

---
function robotmgr.add_robot_to_match(match_level, robot_num, base_diamond)
    local match_level = match_level or 1
    local robot_num = robot_num or 1
    local base_diamond = base_diamond or 10
    filelog.sys_error("-------robotmgr.add_robot_to_match------", match_level, robot_num, base_diamond)

    for i = 1, robot_num do
        local robot = robotmgr.cretae_robot({}, base_diamond)
        if robot then
            ---进入匹配队列
            local request = {
                match_type = match_level,
                gps_addr = "",
            }
            local is_tablerobot = true
            local status, result = skynet.pcall(skynet.call, ".router", "lua", "entermatchtable", robot.rid, robot.roledata, request, is_tablerobot)
            filelog.sys_error("------------add_robot_to_match-------", status, result)
        end
    end
end

function robotmgr.handler.get_robotinfo()
    if not robotmgr.robotpool or #(robotmgr.robotpool) < 1 then
        return nil
    end
    local len = #(robotmgr.robotpool)
    local idx = math.random(1,len)
    local robotinfo = robotmgr.robotpool[idx]
    robotmgr.robotpool[idx] = robotmgr.robotpool[len]
    robotmgr.robotpool[len] = nil
    return robotinfo
end

--移除一个机器人
function robotmgr.remove_robot(rid)
    if not robot_list[rid] then
        return
    end

    --在桌子内，让机器人离桌
    if robot_list[rid] ~= 0 then
        local result = skynet.call(robot_list[rid], "lua", "leavetable", rid, {}, {})   --尝试离桌
        if not result or result.retcode ~= nil then
            skynet.send(robot_list[rid], "lua", "cmd", "delay_leave", rid)   --延迟离开，本局结束再离桌
        end
    else
        robotmgr.delete_robot(rid)
    end
end

function robotmgr.delete_robot(rid)
    if robot_list[rid] then
        robot_list[rid] = nil
        cur_robot_num = cur_robot_num - 1
        table.insert( robotmgr.robotpool, robotmgr.robotinfo_list[rid])
        robotmgr.robotinfo_list[rid] = nil
    end
end

--移除一些机器人
function robotmgr.remove_robots(rids, num)
    num = num or #rids

    --低于最小机器人数，不离桌
    if cur_robot_num - num < robotmgr.min_robot_num then
        num = cur_robot_num - robotmgr.min_robot_num
    end

    if num <= 0 then
        return
    end

    local cnt = 0
    for _,rid in pairs(rids) do
        robotmgr.remove_robot(rid)
        cnt = cnt + 1
        if cnt == num then
            break
        end
    end
end

-----------
function robotmgr.matchresultN(rids, message, retcode, retstr)
    filelog.sys_error("-----robotmgr.matchresultN------", rids, message, retcode, retstr)
    if retcode ~= nil or retstr ~= nil then
        filelog.sys_error("------dn tablerobot matchresultN----", rids, message, retcode, retstr)
        return 
    end
    if next(rids) == nil then return end
    for index, rid in ipairs(rids) do
        local robot_data = robotmgr.create_robotpool[rid]
        if robot_data then
            if message.table_service then robot_data.table_address = message.table_service end
            if message.table_index then robot_data.table_index = message.table_index end
            local msgbody = {}
            local status, result = skynet.pcall(skynet.call, robot_data.table_address, "lua", "reentertable", robot_data.rid, robot_data.roledata, msgbody)
        end
    end
end

function robotmgr.doready(rids)
    filelog.sys_error("----robotmgr.doready-----", rids)
    if not rids or next(rids) == nil then return end
    local function do_ready(rid)
        local sleep_time = base.get_random(10,80)
        skynet.sleep(sleep_time)
        local robot_data = robotmgr.create_robotpool[rid]
        if robot_data then
            if robot_data.table_address > 0 then
                local is_leave = skynet.call(".slotmgr", "lua", "get_can_leveltable", robot_data.roledata.already_game_num)
                ---filelog.sys_error("---------is_leave---------", is_leave)
                if is_leave == true then
                    local msgbody = {}
                    local status, result = skynet.pcall(skynet.call, robot_data.table_address, "lua", "leavetable", robot_data.rid, robot_data.roledata, msgbody)
                    robotmgr.delete_robot(rid)
                else
                    local msgbody = {}
                    local status, result = skynet.pcall(skynet.call, robot_data.table_address, "lua", "gameready", robot_data.rid, robot_data.roledata, msgbody)
                end
            end 
        end
    end
    for _, rid in ipairs(rids) do
        skynet.fork(do_ready, rid)
    end
end

function robotmgr.callbanker(rid, times)
    local robot_data = robotmgr.create_robotpool[rid]
    if robot_data then
        if robot_data.table_address > 0 then
            local msgbody = {
                action_type = DNActionType.ACTION_QIANGZHUANG,
                times = times,
            }
            if times == 0 then
                msgbody.action_type = DNActionType.ACTION_BUQIANG
                msgbody.times = 1
            end
            ---filelog.sys_error("---------callbanker-----", rid, times)
            local status, result = skynet.pcall(skynet.call, robot_data.table_address, "lua", "doaction", robot_data.rid, robot_data.roledata, msgbody)
            ---filelog.sys_error("--------robotmgr.callbanker----", rid, status, result)
        end
    end
end

function robotmgr.dobets(rid, times)
    local function do_bets(rid, times)
        local robot_data = robotmgr.create_robotpool[rid]
        if robot_data then
            if robot_data.table_address > 0 then
                local msgbody = {
                    action_type = DNActionType.ACTION_XIAZHU,
                    times = times or 1,
                }
                filelog.sys_error("---------dobets---------", rid, times)
                local status, result = skynet.pcall(skynet.call, robot_data.table_address, "lua", "doaction", robot_data.rid, robot_data.roledata, msgbody)
                filelog.sys_error("--------robotmgr.dobets----", rid, status, result)
            end
        end
    end
    skynet.fork(do_bets, rid, times)
end

function robotmgr.update_balance(balanceinfos, comments)
    if next(balanceinfos) == nil then return end
    filelog.sys_error("---------robotmgr.update_balance--------", balanceinfos, "----robotmgr-comments----", comments)
    for rid, balanceobj in pairs(balanceinfos) do
        local robot_data = robotmgr.create_robotpool[rid]
        if robot_data then
            local money = robot_data.roledata.money
            money.diamond = money.diamond + balanceobj.value
            robot_data.roledata.already_game_num = robot_data.roledata.already_game_num + 1
            filelog.sys_error("------already_game_num------", rid, robot_data.roledata.already_game_num)
        end
    end
end

function robotmgr.kaipai(rids)
    local function do_kaipai(rid)
        local robot_data = robotmgr.create_robotpool[rid]
        if robot_data then
            if robot_data.table_address > 0 then
                local random_temp = base.get_random(1,100)
                skynet.sleep(random_temp)
                local msgbody = {
                    action_type = DNActionType.ACTION_KAIPAI,
                    times = 0,
                }
                local status, result = skynet.pcall(skynet.call, robot_data.table_address, "lua", "doaction", robot_data.rid, robot_data.roledata, msgbody)
            end
        end
    end
    for index, rid in ipairs(rids) do
        skynet.fork(do_kaipai, rid)
    end
end

function robotmgr.handler.gen_robotinfo(num)
    local status,result = skynet.pcall(cluster.call, "robotnode", ".router", "gen_robotinfo", num)
    if status and result then
        for _,robotinfo in pairs(result) do
            table.insert(robotmgr.robotpool, robotinfo)
        end
        return true
    else
        return false
    end
end

function robotmgr.handler.save_robotinfos()
    local robot_infos = {}
    for _, robot_info in pairs(robotmgr.robotpool) do
        table.insert(robot_infos, robot_info)
    end
    local status,result = skynet.pcall(cluster.call, "robotnode", ".router", "save_robotinfo", robot_infos)
end


--设置机器人状态
function robotmgr.CMD.set_game_robot_state(is_run)
    if is_run then
        robotmgr.is_runrobot = true
    else
        robotmgr.is_runrobot = false
        --踢掉所有机器人
        robotmgr.remove_allrobot()
    end
end

--获得机器人状态
function robotmgr.CMD.get_game_robot_state()
    return robotmgr.is_runrobot
end

--获得机器人数目
function robotmgr.CMD.get_game_robot_num()
    return cur_robot_num
end

---
function robotmgr.CMD.game_end()
    robotmgr.handler.save_robotinfos()
end

function robotmgr:init()
    skynet.fork(function()
        local status = robotmgr.handler.gen_robotinfo(20)
        while(status == false) do
            skynet.sleep(20)
            status = robotmgr.handler.gen_robotinfo(20)
        end
    end)
end

function robotmgr:start()
    skynet.dispatch("lua",function(session, source, cmd, ...)
        local f = robotmgr.CMD[cmd]
        if f then
            skynet.retpack(f(...))
        elseif robotmgr.is_runrobot then
            f = robotmgr[cmd]
            if f then
                skynet.retpack(f(...))
            else
                skynet.retpack()
            end
        else
            skynet.retpack()
        end
    end)
end

skynet.start(function() 
    robotmgr:start()
    robotmgr:init()
end)